归并排序的基本思想也是分治法。与快速排序不一样的是,归并排序是先分后治,而快排是先治后分

可以看到这种结构很像一棵完全二叉树,本文的归并排序我们采用递归去实现。
分
在分的阶段可以采用递归方法实现:
1 2 3 4 5 6 7 8 9
| void mergeSort(int *arr,int start,int end){ if(start>=end)return; int mid=start+(end-start)/2; mergeSort(arr,start,mid); mergeSort(arr,mid+1,end); merge(arr,start,mid,end,temp); }
|
治
在治的阶段将问题转化为了合并相邻有序子序列:
例如,{8}和{4}{4,8}和{5,7}{4,5,7,8}和{1,2,3,6}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| void merge(int *arr,int start,int mid,int end,int *temp){ int i=start; int j=mid+1; int k=0; while(i<=mid && j<=end){ temp[k++]=((arr[i]<arr[j])?arr[i++]:arr[j++]); } while(i<=mid){ temp[k++]=arr[i++]; } while(j<=end){ temp[k++]=arr[j++]; } k=0; while(start<=end){ arr[start++]=arr[k++]; } }
|
时间复杂度:
合并操作merge()的平均复杂度是$O(N)$
拆分操作是完全二叉树的深度,时间复杂度是$O(NlogN)$
所以,最坏、最好和平均时间复杂度都是$O(NlogN)$。
稳定排序
优缺点
缺点:需要额外的空间。开辟与arr数组一样大小的空间来存储排好的序列。
参考